;;; init-funcs.el --- core functions -*- lexical-binding: t -*-
;;; Commentary:
;;

;;; Code:

;;;###autoload
(defun +rename-current-file (newname)
  "Rename current visiting file to NEWNAME.
If NEWNAME is a directory, move file to it."
  (interactive
   (progn
     (unless buffer-file-name
       (user-error "No file is visiting"))
     (let ((name (read-file-name "Rename to: " nil buffer-file-name 'confirm)))
       (when (equal (file-truename name)
                    (file-truename buffer-file-name))
         (user-error "Can't rename file to itself"))
       (list name))))
  ;; NEWNAME is a directory
  (when (equal newname (file-name-as-directory newname))
    (setq newname (concat newname (file-name-nondirectory buffer-file-name))))
  (rename-file buffer-file-name newname)
  (set-visited-file-name newname)
  (rename-buffer newname))

;;;###autoload
(defun +delete-current-file (file)
  "Delete current visiting FILE."
  (interactive
   (list (or buffer-file-name
             (user-error "No file is visiting"))))
  (when (y-or-n-p (format "Really delete '%s'? " file))
    (kill-this-buffer)
    (delete-file file)))

;;;###autoload
(defun +copy-current-file (new-path &optional overwrite-p)
  "Copy current buffer's file to `NEW-PATH'.
If `OVERWRITE-P', overwrite the destination file without
confirmation."
  (interactive
   (progn
     (unless buffer-file-name
       (user-error "No file is visiting"))
     (list (read-file-name "Copy file to: ")
           current-prefix-arg)))
  (let ((old-path (buffer-file-name))
        (new-path (expand-file-name new-path)))
    (make-directory (file-name-directory new-path) t)
    (copy-file old-path new-path (or overwrite-p 1))))

;;;###autoload
(defun +copy-current-filename (file)
  "Copy the full path to the current FILE."
  (interactive
   (list (or buffer-file-name
             (user-error "No file is visiting"))))
  (kill-new file)
  (message "Copying '%s' to clipboard" file))

;;;###autoload
(defun +copy-current-buffer-name ()
  "Copy the name of current buffer."
  (interactive)
  (kill-new (buffer-name))
  (message "Copying '%s' to clipboard" (buffer-name)))

;;;###autoload
(defun +transient-tab-bar-history ()
  "Transient map of command `tab-bar-history'."
  (interactive)
  (let ((echo-keystrokes nil))
    (tab-bar-history-back)
    (message "tab-bar-history: [u]back [r]forward")
    (set-transient-map
     (let ((map (make-sparse-keymap)))
       (define-key map "u" #'tab-bar-history-back)
       (define-key map "r" #'tab-bar-history-forward)
       map)
     t)))

(defun open-config ()
  "Open personal config."
  (interactive)
  (find-file "~/.emacs.d/init.el"))

;; 使用外部文件管理器打开文件夹
(defun open-directory-externally (file)
  "Open FILE externally using the default application of the system."
  (interactive "fOpen externally: ")
  (if (and (eq system-type 'windows-nt)
	   (fboundp 'w32-shell-execute))
      (let ((target-string "\\\\"))
	(if (string-search "msys" (expand-file-name "~"))
	    (setq target-string "\\\\\\\\"))
	(shell-command-to-string (encode-coding-string (replace-regexp-in-string "/" target-string
	    (format "explorer.exe %s" (file-name-directory (expand-file-name file)))) 'gbk)))
    (call-process (pcase system-type
		    ('darwin "open")
		    ('cygwin "cygstart")
		    (_ "xdg-open"))
		  nil 0 nil
		  (file-name-directory (expand-file-name file))))
  (keyboard-quit))


(defun gotpl/copy-file-path (file)
  "copy file path."
  (kill-new (expand-file-name file))
  
  )

(defun prot-simple-rename-file-and-buffer (name)
  "Apply NAME to current file and rename its buffer.
Do not try to make a new directory or anything fancy."
  (interactive
   (list (read-string "Rename current file: " (buffer-file-name))))
  (let ((file (buffer-file-name)))
    (if (vc-registered file)
        (vc-rename-file file name)
      (rename-file file name))
    (set-visited-file-name name t t)))

;;打开当前文件的目录
(defun my-open-current-directory ()
  (interactive)
  (consult-directory-externally default-directory))

(defun embark-export-write ()
  "Export the current vertico results to a writable buffer if possible.
Supports exporting consult-grep to wgrep, file to wdeired, and consult-location to occur-edit"
  (interactive)
  (require 'embark)
  (require 'wgrep)
  (pcase-let ((`(,type . ,candidates)
               (run-hook-with-args-until-success 'embark-candidate-collectors)))
    (pcase type
      ('consult-grep (let ((embark-after-export-hook #'wgrep-change-to-wgrep-mode))
                       (embark-export)))
      ('file (let ((embark-after-export-hook #'wdired-change-to-wdired-mode))
               (embark-export)))
      ('consult-location (let ((embark-after-export-hook #'occur-edit-mode))
                           (embark-export)))
      (x (user-error "embark category %S doesn't support writable export" x)))))

;; Configure network proxy
(setq my-proxy "127.0.0.1:7890") 
(defun show-proxy ()
  "Show http/https proxy."
  (interactive)
  (if url-proxy-services
      (message "Current proxy is \"%s\"" my-proxy)
    (message "No proxy")))

(defun set-proxy ()
  "Set http/https proxy."
  (interactive)
  (setq url-proxy-services `(("http" . ,my-proxy)
                             ("https" . ,my-proxy)))
  (show-proxy))

(defun unset-proxy ()
  "Unset http/https proxy."
  (interactive)
  (setq url-proxy-services nil)
  (show-proxy))

(defun toggle-proxy ()
  "Toggle http/https proxy."
  (interactive)
  (if url-proxy-services
      (unset-proxy)
    (set-proxy)))

;; 创建文件
(defun create-files-if-not-exist (file-list)
  "Create files in the FILE-LIST if they do not exist."
  (dolist (file file-list)
    (unless (file-exists-p file)
      (with-temp-buffer
        (write-file file)))))


;; 根据filepath向上寻找包含lst列表中的元素，第一个包含的文件或文件夹被返回，否则nil
(defun check-locate (lst filepath)
  (if (null lst)
      nil
    (let ((result (locate-dominating-file filepath (car lst))))
      (if result
          (expand-file-name result)
        (check-locate (cdr lst) filepath)))))
;; (locate-dominating-file "/home/gotpl/personal/new_proj/labtask/deploy/ShipDetect" ".git")
;; (check-locate '(".git" ".projectile") "/home/gotpl/personal/new_proj/labtask/deploy")


(defun save-var-to-file (var-value file-path)
  "将变量的值保存到指定的文件中。"
  (with-temp-file file-path
    (pp var-value (current-buffer))))
(defun load-var-from-file (file-path)
  "从指定的文件中加载变量的值。"
  (if (file-exists-p file-path)
      (with-temp-buffer
        (insert-file-contents file-path)
        (read (current-buffer)))
    nil))
(defun update-var-in-file (new-element file-path &optional unique)
  "更新文件中的变量，插入新的元素。如果变量不存在，则创建它。unique t 列表唯一，不重复添加"
  (let ((var-value (or (load-var-from-file file-path) '()))) ; 加载或初始化变量
    ;; 如果元素不在列表中，添加它
    (if (not (and unique (member new-element var-value)))
      (setq var-value (append var-value (list new-element))))
    ;; 保存更新后的变量回文件
    (save-var-to-file var-value file-path)))

(defun find-file-in-dir (dir)
  (when (not (featurep 'project))
    (require 'project))
  (let* (
         (dirs (list dir))
         (project `(vc Git ,@dirs))
         (all-files (project-files project dirs))
         (file (funcall project-read-file-name-function
                        "Find file" all-files nil 'file-name-history
                        nil)))
    (if (string= file "")
        (user-error "You didn't specify the file")
      (find-file file))
    ))

(defun find-files-in-config-dir ()
  (interactive)
  (find-file-in-dir user-emacs-directory)
  )

(defun gcc-is-executable ()
  (executable-find "gcc"))

(defun linux/get-arch ()
  (replace-regexp-in-string "\n" "" (shell-command-to-string "uname -m")))

(defun detect-cpu-architecture ()
  "检测当前系统的 CPU 架构。"
  (interactive)
  (cond
   ;; 对于 Windows 系统
   ((string-equal system-type "windows-nt")
    (let ((arch-output (shell-command-to-string "wmic os get osarchitecture")))
      (cond
       ((string-match "64-bit" arch-output) "x64 架构")
       ((string-match "32-bit" arch-output) "x86 架构")
       (t "未知架构"))))
   ;; 对于 GNU/Linux 系统
   ((string-equal system-type "gnu/linux")
    (let ((arch-output (shell-command-to-string "uname -m")))
      (cond
       ((string-match "x86_64" arch-output) "x64 架构")
       ((string-match "i686\\|i386" arch-output) "x86 架构")
       ((string-match "arm" arch-output) "ARM 架构")
       (t "未知架构"))))
   ;; 默认情况
   (t "不支持的操作系统类型")))

(message "您的 CPU 架构是：%s" (detect-cpu-architecture))


(provide 'init-funcs)
;;; init-funcs.el ends here
